﻿namespace LinFu.AOP.Interfaces
{
    public abstract class BaseMethodReplacementProvider : IMethodReplacementProvider, IAroundInvoke, IMethodReplacement
    {
        #region Fields

        private ICallCounter _counter = new MultiThreadedCallCounter();

        #endregion Fields

        #region Constructors

        protected BaseMethodReplacementProvider()
        {
        }

        #endregion Constructors

        #region Methods

        public void AfterInvoke(IInvocationContext context, object returnValue)
        {
            _counter.Decrement(context);
        }

        public void BeforeInvoke(IInvocationContext context)
        {
            _counter.Increment(context);
        }

        public bool CanReplace(IInvocationContext context)
        {
            if (context == null)
                return false;

            int pendingCalls = _counter.GetPendingCalls(context);

            if (pendingCalls > 0)
                return false;

            return ShouldReplace(context);
        }

        public IMethodReplacement GetMethodReplacement(IInvocationContext context)
        {
            int pendingCalls = _counter.GetPendingCalls(context);

            if (pendingCalls > 0)
                return null;

            return GetReplacement(context);
        }

        public virtual object Invoke(IInvocationContext context)
        {
            return null;
        }

        public virtual bool ShouldReplace(IInvocationContext context)
        {
            return true;
        }

        protected abstract IMethodReplacement GetReplacement(IInvocationContext context);

        #endregion Methods
    }
}